home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / dflat8.zip / NORMAL.C < prev    next >
Text File  |  1991-09-30  |  31KB  |  994 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. static void near PaintOverLappers(WINDOW wnd);
  6. static void near PaintUnderLappers(WINDOW wnd);
  7. static int InsideWindow(WINDOW, int, int);
  8. static void TerminateMoveSize(void);
  9. static void SaveBorder(RECT);
  10. static void RestoreBorder(RECT);
  11. static RECT PositionIcon(WINDOW);
  12. static void near dragborder(WINDOW, int, int);
  13. static void near sizeborder(WINDOW, int, int);
  14. static int px = -1, py = -1;
  15. static int diff;
  16. static int conditioning;
  17. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc,
  18.                                 {-1,-1,-1,-1}};
  19. static int *Bsave;
  20. static int Bht, Bwd;
  21. int WindowMoving;
  22. int WindowSizing;
  23. /* -------- array of class definitions -------- */
  24. CLASSDEFS classdefs[] = {
  25.     #undef ClassDef
  26.     #define ClassDef(c,b,p,a) {b,p,a},
  27.     #include "classes.h"
  28. };
  29. WINDOW HiddenWindow;
  30.  
  31. static void CreateWindowMsg(WINDOW wnd)
  32. {
  33.     AppendBuiltWindow(wnd);  /* add to the lists */
  34.     AppendFocusWindow(wnd);
  35.     if (!SendMessage(NULL, MOUSE_INSTALLED, 0, 0))
  36.         ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  37.     if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  38.         GetVideoBuffer(wnd);
  39. }
  40.  
  41. static void ShowWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  42. {
  43.     if ((GetParent(wnd) == NULL ||
  44.                 isVisible(GetParent(wnd)))
  45.                     && !conditioning)    {
  46.         WINDOW cwnd = Focus.FirstWindow;
  47.         if (TestAttribute(wnd, SAVESELF) &&
  48.                         wnd->videosave == NULL)
  49.             GetVideoBuffer(wnd);
  50.         SetVisible(wnd);
  51.         SendMessage(wnd, PAINT, 0, 0);
  52.         SendMessage(wnd, BORDER, 0, 0);
  53.         /* --- show the children of this window --- */
  54.         while (cwnd != NULL)    {
  55.             if (GetParent(cwnd) == wnd &&
  56.                     cwnd->condition != ISCLOSING &&
  57.                         isVisible(cwnd))
  58.                 SendMessage(cwnd, SHOW_WINDOW, p1, p2);
  59.             cwnd = NextWindow(cwnd);
  60.         }
  61.     }
  62. }
  63.  
  64. static void HideWindowMsg(WINDOW wnd)
  65. {
  66.     if (isVisible(wnd) && !conditioning)    {
  67.         ClearVisible(wnd);
  68.         /* --- paint what this window covered --- */
  69.         if (wnd->videosave != NULL)
  70.             RestoreVideoBuffer(wnd);
  71.         else
  72.             PaintOverLappers(wnd);
  73.     }
  74. }
  75.  
  76. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  77. {
  78.     if (WindowMoving || WindowSizing)    {
  79.         /* -- move or size a window with keyboard -- */
  80.         int x, y;
  81.         x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  82.         y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  83.         switch ((int)p1)    {
  84.             case ESC:
  85.                 TerminateMoveSize();
  86.                 return TRUE;
  87.             case UP:
  88.                 if (y)
  89.                     --y;
  90.                 break;
  91.             case DN:
  92.                 if (y < SCREENHEIGHT-1)
  93.                     y++;
  94.                 break;
  95.             case FWD:
  96.                 if (x < SCREENWIDTH-1)
  97.                     x++;
  98.                 break;
  99.             case BS:
  100.                 if (x)
  101.                     --x;
  102.                 break;
  103.             case '\r':
  104.                 SendMessage(wnd,BUTTON_RELEASED,x,y);
  105.             default:
  106.                 return TRUE;
  107.         }
  108.         /* -- use the mouse functions to move/size - */
  109.         SendMessage(wnd, MOUSE_CURSOR, x, y);
  110.         SendMessage(wnd, MOUSE_MOVED, x, y);
  111.         return TRUE;
  112.     }
  113.     switch ((int)p1)    {
  114.         case F1:
  115.             SendMessage(wnd, COMMAND, ID_HELP, 0);
  116.             return TRUE;
  117.         case ' ':
  118.             if ((int)p2 & ALTKEY)
  119.                 if (TestAttribute(wnd, HASTITLEBAR))
  120.                     if (TestAttribute(wnd, CONTROLBOX))
  121.                         BuildSystemMenu(wnd);
  122.             return TRUE;
  123.         case CTRL_F4:
  124.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  125.             SkipSystemWindows(FALSE);
  126.             return TRUE;
  127.         default:
  128.             break;
  129.     }
  130.     return FALSE;
  131. }
  132.  
  133. static void CommandMsg(WINDOW wnd, PARAM p1)
  134. {
  135.     switch ((int)p1)    {
  136.         case ID_HELP:
  137.             DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
  138.             break;
  139.         case ID_SYSRESTORE:
  140.             SendMessage(wnd, RESTORE, 0, 0);
  141.             break;
  142.         case ID_SYSMOVE:
  143.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  144.                 (PARAM) &dwnd);
  145.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  146.                 (PARAM) &dwnd);
  147.             SendMessage(wnd, MOUSE_CURSOR,
  148.                 GetLeft(wnd), GetTop(wnd));
  149.             WindowMoving = TRUE;
  150.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  151.             break;
  152.         case ID_SYSSIZE:
  153.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  154.                 (PARAM) &dwnd);
  155.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  156.                 (PARAM) &dwnd);
  157.             SendMessage(wnd, MOUSE_CURSOR,
  158.                 GetRight(wnd), GetBottom(wnd));
  159.             WindowSizing = TRUE;
  160.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  161.             break;
  162.         case ID_SYSMINIMIZE:
  163.             SendMessage(wnd, MINIMIZE, 0, 0);
  164.             break;
  165.         case ID_SYSMAXIMIZE:
  166.             SendMessage(wnd, MAXIMIZE, 0, 0);
  167.             break;
  168.         case ID_SYSCLOSE:
  169.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  170.             break;
  171.         default:
  172.             break;
  173.     }
  174. }
  175.  
  176. static void ReFocus(WINDOW wnd, WINDOW Self)
  177. {
  178.     WINDOW pwnd = GetParent(wnd);
  179.     WINDOW cwnd = Built.FirstWindow;
  180.     /* refocus all ancestors down to but not including APPLICATION */
  181.     if (Self != (WINDOW)-1 && pwnd != NULL)
  182.         if (GetClass(pwnd) != APPLICATION)
  183.             ReFocus(pwnd, wnd);
  184.     /* refocus all children of this window */
  185.        while (cwnd != NULL)    {
  186.         if (cwnd != Self && GetParent(cwnd) == wnd)
  187.             ReFocus(cwnd, (WINDOW) -1);
  188.         cwnd = NextWindowBuilt(cwnd);
  189.     }
  190.     /* remove window from Focus list */
  191.        RemoveFocusWindow(wnd);
  192.     /* move window to end of Focus list */
  193.     AppendFocusWindow(wnd);
  194. }
  195.  
  196. static void SetFocusMsg(WINDOW wnd, PARAM p1)
  197. {
  198.     if (p1 && inFocus != wnd)    {
  199.         /* ---- setting focus ------ */
  200.         WINDOW pwnd = GetParent(wnd);
  201.         int Redraw = !TestAttribute(wnd, SAVESELF) && isVisible(wnd);
  202.         AddAttribute(wnd, VISIBLE);
  203.         if (GetClass(pwnd) == APPLICATION)    {
  204.             WINDOW cwnd = Focus.FirstWindow;
  205.             /* -- if no children, do not need selective
  206.                 redraw --- */
  207.             while (cwnd != NULL)    {
  208.                 if (GetParent(cwnd) == wnd)
  209.                     break;
  210.                 cwnd = NextWindow(cwnd);
  211.             }
  212.             if (cwnd == NULL)
  213.                 Redraw = FALSE;
  214.         }
  215.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  216.  
  217.         inFocus = wnd;
  218.  
  219.         if (Redraw)    {
  220.             PaintUnderLappers(GetAncestor(wnd));
  221.             ReFocus(wnd, NULL);
  222.             SendMessage(wnd, BORDER, 0, 0);
  223.         }
  224.         else    {
  225.             ReFocus(wnd, NULL);
  226.             if (pwnd == NULL ||
  227.                 isDerivedFrom(pwnd, DIALOG) ||
  228.                     isDerivedFrom(pwnd, APPLICATION))
  229.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  230.             else
  231.                 SendMessage(pwnd, SHOW_WINDOW, 0, 0);
  232.         }
  233.     }
  234.     else if (!p1 && inFocus == wnd)    {
  235.         /* -------- clearing focus --------- */
  236.         inFocus = NULL;
  237.         SendMessage(wnd, BORDER, 0, 0);
  238.     }
  239. }
  240.  
  241. static void DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  242. {
  243.     int mx = (int) p1 - GetLeft(wnd);
  244.     int my = (int) p2 - GetTop(wnd);
  245.     if (!WindowSizing && !WindowMoving)
  246.         if (HitControlBox(wnd, mx, my))
  247.             PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  248. }
  249.  
  250. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  251. {
  252.     int mx = (int) p1 - GetLeft(wnd);
  253.     int my = (int) p2 - GetTop(wnd);
  254.     if (WindowSizing || WindowMoving)
  255.         return;
  256.     if (HitControlBox(wnd, mx, my))    {
  257.         BuildSystemMenu(wnd);
  258.         return;
  259.     }
  260.     if (my == 0 && mx > -1 && mx < WindowWidth(wnd))  {
  261.         /* ---------- hit the top border -------- */
  262.         if (TestAttribute(wnd, MINMAXBOX) &&
  263.                 TestAttribute(wnd, HASTITLEBAR))  {
  264.             if (mx == WindowWidth(wnd)-2)    {
  265.                 if (wnd->condition == ISRESTORED)
  266.                     /* --- hit the maximize box --- */
  267.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  268.                 else
  269.                     /* --- hit the restore box --- */
  270.                     SendMessage(wnd, RESTORE, 0, 0);
  271.                 return;
  272.             }
  273.             if (mx == WindowWidth(wnd)-3)    {
  274.                 /* --- hit the minimize box --- */
  275.                 if (wnd->condition != ISMINIMIZED)
  276.                     SendMessage(wnd, MINIMIZE, 0, 0);
  277.                 return;
  278.             }
  279.         }
  280.         if (wnd->condition != ISMAXIMIZED &&
  281.                     TestAttribute(wnd, MOVEABLE))    {
  282.             WindowMoving = TRUE;
  283.             px = mx;
  284.             py = my;
  285.             diff = (int) mx;
  286.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  287.                 (PARAM) &dwnd);
  288.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  289.         }
  290.         return;
  291.     }
  292.     if (mx == WindowWidth(wnd)-1 &&
  293.             my == WindowHeight(wnd)-1)    {
  294.         /* ------- hit the resize corner ------- */
  295.         if (wnd->condition == ISMINIMIZED ||
  296.                 !TestAttribute(wnd, SIZEABLE))
  297.             return;
  298.         if (wnd->condition == ISMAXIMIZED)    {
  299.             if (TestAttribute(GetParent(wnd),HASBORDER))
  300.                 return;
  301.             /* ----- resizing a maximized window over a
  302.                     borderless parent ----- */
  303.             wnd = GetParent(wnd);
  304.         }
  305.         WindowSizing = TRUE;
  306.         SendMessage(wnd, CAPTURE_MOUSE,
  307.             TRUE, (PARAM) &dwnd);
  308.         dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  309.     }
  310. }
  311.  
  312. static int MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  313. {
  314.     if (WindowMoving)    {
  315.         int leftmost = 0, topmost = 0,
  316.             bottommost = SCREENHEIGHT-2,
  317.             rightmost = SCREENWIDTH-2;
  318.         int x = (int) p1 - diff;
  319.         int y = (int) p2;
  320.         if (GetParent(wnd) != NULL &&
  321.                 !TestAttribute(wnd, NOCLIP))    {
  322.             WINDOW wnd1 = GetParent(wnd);
  323.             topmost    = GetClientTop(wnd1);
  324.             leftmost   = GetClientLeft(wnd1);
  325.             bottommost = GetClientBottom(wnd1);
  326.             rightmost  = GetClientRight(wnd1);
  327.         }
  328.         if (x < leftmost || x > rightmost ||
  329.                 y < topmost || y > bottommost)    {
  330.             x = max(x, leftmost);
  331.             x = min(x, rightmost);
  332.             y = max(y, topmost);
  333.             y = min(y, bottommost);
  334.             SendMessage(NULL,MOUSE_CURSOR,x+diff,y);
  335.         }
  336.         if (x != px || y != py)    {
  337.             px = x;
  338.             py = y;
  339.             dragborder(wnd, x, y);
  340.         }
  341.         return TRUE;
  342.     }
  343.     if (WindowSizing)    {
  344.         sizeborder(wnd, (int) p1, (int) p2);
  345.         return TRUE;
  346.     }
  347.     return FALSE;
  348. }
  349.  
  350. static void MaximizeMsg(WINDOW wnd)
  351. {
  352.     RECT rc = {0, 0, 0, 0};
  353.     RECT holdrc;
  354.     holdrc = wnd->RestoredRC;
  355.     rc.rt = SCREENWIDTH-1;
  356.     rc.bt = SCREENHEIGHT-1;
  357.     if (GetParent(wnd))
  358.         rc = ClientRect(GetParent(wnd));
  359.     wnd->oldcondition = wnd->condition;
  360.     wnd->condition = ISMAXIMIZED;
  361.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  362.     conditioning = TRUE;
  363.     SendMessage(wnd, MOVE,
  364.         RectLeft(rc), RectTop(rc));
  365.     SendMessage(wnd, SIZE,
  366.         RectRight(rc), RectBottom(rc));
  367.     conditioning = FALSE;
  368.     if (wnd->restored_attrib == 0)
  369.         wnd->restored_attrib = wnd->attrib;
  370.     ClearAttribute(wnd, SHADOW);
  371.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  372.     wnd->RestoredRC = holdrc;
  373. }
  374.  
  375. static void MinimizeMsg(WINDOW wnd)
  376. {
  377.     RECT rc;
  378.     RECT holdrc;
  379.  
  380.     holdrc = wnd->RestoredRC;
  381.     rc = PositionIcon(wnd);
  382.     wnd->oldcondition = wnd->condition;
  383.     wnd->condition = ISMINIMIZED;
  384.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  385.     conditioning = TRUE;
  386.     SendMessage(wnd, MOVE,
  387.         RectLeft(rc), RectTop(rc));
  388.     SendMessage(wnd, SIZE,
  389.         RectRight(rc), RectBottom(rc));
  390.     SetPrevFocus(wnd);
  391.     conditioning = FALSE;
  392.     if (wnd->restored_attrib == 0)
  393.         wnd->restored_attrib = wnd->attrib;
  394.     ClearAttribute(wnd,
  395.         SHADOW | SIZEABLE | HASMENUBAR |
  396.         VSCROLLBAR | HSCROLLBAR);
  397.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  398.     wnd->RestoredRC = holdrc;
  399. }
  400.  
  401. static void RestoreMsg(WINDOW wnd)
  402. {
  403.     RECT holdrc;
  404.     holdrc = wnd->RestoredRC;
  405.     wnd->oldcondition = wnd->condition;
  406.     wnd->condition = ISRESTORED;
  407.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  408.     wnd->attrib = wnd->restored_attrib;
  409.     wnd->restored_attrib = 0;
  410.     conditioning = TRUE;
  411.     SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  412.         wnd->RestoredRC.tp);
  413.     wnd->RestoredRC = holdrc;
  414.     SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  415.         wnd->RestoredRC.bt);
  416.     SendMessage(wnd, SETFOCUS, TRUE, 0);
  417.     conditioning = FALSE;
  418.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  419. }
  420.  
  421. static void MoveMsg(WINDOW wnd, PARAM p1, PARAM p2)
  422. {
  423.     WINDOW wnd1 = Focus.FirstWindow;
  424.     int wasVisible = isVisible(wnd);
  425.     int xdif = (int) p1 - wnd->rc.lf;
  426.     int ydif = (int) p2 - wnd->rc.tp;
  427.  
  428.     if (xdif == 0 && ydif == 0)
  429.         return;
  430.     if (wasVisible)
  431.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  432.     wnd->rc.lf = (int) p1;
  433.     wnd->rc.tp = (int) p2;
  434.     wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  435.     wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  436.     if (wnd->condition == ISRESTORED)
  437.         wnd->RestoredRC = wnd->rc;
  438.     while (wnd1 != NULL)    {
  439.         if (GetParent(wnd1) == wnd)
  440.             SendMessage(wnd1, MOVE,
  441.                 wnd1->rc.lf+xdif, wnd1->rc.tp+ydif);
  442.         wnd1 = NextWindow(wnd1);
  443.     }
  444.     if (wasVisible)
  445.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  446. }
  447.  
  448. static void SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  449. {
  450.     int wasVisible = isVisible(wnd);
  451.     WINDOW wnd1 = Focus.FirstWindow;
  452.     RECT rc;
  453.     int xdif = (int) p1 - wnd->rc.rt;
  454.     int ydif = (int) p2 - wnd->rc.bt;
  455.  
  456.     if (xdif == 0 && ydif == 0)
  457.         return;
  458.     if (wasVisible)
  459.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  460.     wnd->rc.rt = (int) p1;
  461.     wnd->rc.bt = (int) p2;
  462.     wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  463.     wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  464.  
  465.     if (wnd->condition == ISRESTORED)
  466.         wnd->RestoredRC = WindowRect(wnd);
  467.  
  468.     rc = ClientRect(wnd);
  469.     while (wnd1 != NULL)    {
  470.         if (GetParent(wnd1) == wnd &&
  471.                 wnd1->condition == ISMAXIMIZED)
  472.             SendMessage(wnd1, SIZE, RectRight(rc),
  473.                                     RectBottom(rc));
  474.         wnd1 = NextWindow(wnd1);
  475.     }
  476.     if (wasVisible)
  477.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  478. }
  479.  
  480. static void CloseWindowMsg(WINDOW wnd)
  481. {
  482.     int DoneClosing = FALSE;
  483.     wnd->condition = ISCLOSING;
  484.     if (wnd->PrevMouse != NULL)
  485.         SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  486.     if (wnd->PrevKeyboard != NULL)
  487.         SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  488.     /* ----------- hide this window ------------ */
  489.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  490.     /* --- close the children of this window --- */
  491.     while (!DoneClosing)    {
  492.         WINDOW wnd1 = Focus.LastWindow;
  493.         DoneClosing = TRUE;
  494.         while (wnd1 != NULL)    {
  495.             WINDOW prwnd = PrevWindow(wnd1);
  496.             if (GetParent(wnd1) == wnd)    {
  497.                 if (inFocus == wnd1)    {
  498.                     RemoveFocusWindow(wnd);
  499.                     AppendFocusWindow(wnd);
  500.                     inFocus = wnd;
  501.                 }
  502.                 SendMessage(wnd1,CLOSE_WINDOW,0,0);
  503.                 DoneClosing = FALSE;
  504.                 break;
  505.             }
  506.             wnd1 = prwnd;
  507.         }
  508.     }
  509.     /* --- change focus if this window had it -- */
  510.     SetPrevFocus(wnd);
  511.     /* ------- remove this window from the
  512.             list of open windows ------------- */
  513.     RemoveBuiltWindow(wnd);
  514.     /* ------- remove this window from the
  515.             list of in-focus windows ---------- */
  516.     RemoveFocusWindow(wnd);
  517.     /* -- free memory allocated to this window - */
  518.     if (wnd->title != NULL)
  519.         free(wnd->title);
  520.     if (wnd->videosave != NULL)
  521.         free(wnd->videosave);
  522.     free(wnd);
  523. }
  524.  
  525. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  526. {
  527.     switch (msg)    {
  528.         case CREATE_WINDOW:
  529.             CreateWindowMsg(wnd);
  530.             break;
  531.         case SHOW_WINDOW:
  532.             ShowWindowMsg(wnd, p1, p2);
  533.             break;
  534.         case HIDE_WINDOW:
  535.             HideWindowMsg(wnd);
  536.             break;
  537.         case DISPLAY_HELP:
  538.             DisplayHelp(wnd, (char *)p1);
  539.             break;
  540.         case INSIDE_WINDOW:
  541.             return InsideWindow(wnd, (int) p1, (int) p2);
  542.         case KEYBOARD:
  543.             if (KeyboardMsg(wnd, p1, p2))
  544.                 return TRUE;
  545.             /* ------- fall through ------- */
  546.         case ADDSTATUS:
  547.         case SHIFT_CHANGED:
  548.             if (GetParent(wnd) != NULL)
  549.                 PostMessage(GetParent(wnd), msg, p1, p2);
  550.             break;
  551.         case PAINT:
  552.             if (isVisible(wnd))    
  553.                 ClearWindow(wnd, (RECT *)p1, ' ');
  554.             break;
  555.         case BORDER:
  556.             if (isVisible(wnd))    {
  557.                 if (TestAttribute(wnd, HASBORDER))
  558.                     RepaintBorder(wnd, (RECT *)p1);
  559.                 else if (TestAttribute(wnd, HASTITLEBAR))
  560.                     DisplayTitle(wnd, (RECT *)p1);
  561.                 if (wnd->StatusBar != NULL)
  562.                     SendMessage(wnd->StatusBar, PAINT, p1, 0);
  563.             }
  564.             break;
  565.         case COMMAND:
  566.             CommandMsg(wnd, p1);
  567.             break;
  568.         case SETFOCUS:
  569.             SetFocusMsg(wnd, p1);
  570.             break;
  571.         case DOUBLE_CLICK:
  572.             DoubleClickMsg(wnd, p1, p2);
  573.             break;
  574.         case LEFT_BUTTON:
  575.             LeftButtonMsg(wnd, p1, p2);
  576.             break;
  577.         case MOUSE_MOVED:
  578.             if (MouseMovedMsg(wnd, p1, p2))
  579.                 return TRUE;
  580.             break;
  581.         case BUTTON_RELEASED:
  582.             if (WindowMoving || WindowSizing)    {
  583.                 if (WindowMoving)
  584.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  585.                 else
  586.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  587.                 TerminateMoveSize();
  588.             }
  589.             break;
  590.         case MAXIMIZE:
  591.             if (wnd->condition != ISMAXIMIZED)
  592.                 MaximizeMsg(wnd);
  593.             break;
  594.         case MINIMIZE:
  595.             if (wnd->condition != ISMINIMIZED)
  596.                 MinimizeMsg(wnd);
  597.             break;
  598.         case RESTORE:
  599.             if (wnd->condition != ISRESTORED)    {
  600.                 if (wnd->oldcondition == ISMAXIMIZED)
  601.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  602.                 else
  603.                     RestoreMsg(wnd);
  604.             }
  605.             break;
  606.         case MOVE:
  607.             MoveMsg(wnd, p1, p2);
  608.             break;
  609.         case SIZE:    {
  610.             SizeMsg(wnd, p1, p2);
  611.             break;
  612.         }
  613.         case CLOSE_WINDOW:
  614.             CloseWindowMsg(wnd);
  615.             break;
  616.         default:
  617.             break;
  618.     }
  619.     return TRUE;
  620. }
  621. /* ---- compute lower left icon space in a rectangle ---- */
  622. static RECT LowerRight(RECT prc)
  623. {
  624.     RECT rc;
  625.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  626.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  627.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  628.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  629.     return rc;
  630. }
  631. /* ----- compute a position for a minimized window icon ---- */
  632. static RECT PositionIcon(WINDOW wnd)
  633. {
  634.     RECT rc;
  635.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  636.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  637.     RectRight(rc) = SCREENWIDTH-1;
  638.     RectBottom(rc) = SCREENHEIGHT-1;
  639.     if (GetParent(wnd))    {
  640.         WINDOW wnd1 = (WINDOW) -1;
  641.         RECT prc;
  642.         prc = WindowRect(GetParent(wnd));
  643.         rc = LowerRight(prc);
  644.         /* - search for icon available location - */
  645.         while (wnd1 != NULL)    {
  646.             wnd1 = GetFirstChild(GetParent(wnd));
  647.             while (wnd1 != NULL)    {
  648.                 if (wnd1->condition == ISMINIMIZED)    {
  649.                     RECT rc1;
  650.                     rc1 = WindowRect(wnd1);
  651.                     if (RectLeft(rc1) == RectLeft(rc) &&
  652.                             RectTop(rc1) == RectTop(rc))    {
  653.                         RectLeft(rc) -= ICONWIDTH;
  654.                         RectRight(rc) -= ICONWIDTH;
  655.                         if (RectLeft(rc) < RectLeft(prc)+1)   {
  656.                             RectLeft(rc) =
  657.                                 RectRight(prc)-ICONWIDTH;
  658.                             RectRight(rc) =
  659.                                 RectLeft(rc)+ICONWIDTH-1;
  660.                             RectTop(rc) -= ICONHEIGHT;
  661.                             RectBottom(rc) -= ICONHEIGHT;
  662.                             if (RectTop(rc) < RectTop(prc)+1)
  663.                                 return LowerRight(prc);
  664.                         }
  665.                         break;
  666.                     }
  667.                 }
  668.                 wnd1 = GetNextChild(GetParent(wnd), wnd1);
  669.             }
  670.         }
  671.     }
  672.     return rc;
  673. }
  674. /* ----- terminate the move or size operation ----- */
  675. static void TerminateMoveSize(void)
  676. {
  677.     px = py = -1;
  678.     diff = 0;
  679.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  680.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  681.     RestoreBorder(dwnd.rc);
  682.     WindowMoving = WindowSizing = FALSE;
  683. }
  684. /* ---- build a dummy window border for moving or sizing --- */
  685. static void near dragborder(WINDOW wnd, int x, int y)
  686. {
  687.     RestoreBorder(dwnd.rc);
  688.     /* ------- build the dummy window -------- */
  689.     dwnd.rc.lf = x;
  690.     dwnd.rc.tp = y;
  691.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  692.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  693.     dwnd.ht = WindowHeight(wnd);
  694.     dwnd.wd = WindowWidth(wnd);
  695.     dwnd.parent = GetParent(wnd);
  696.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  697.     InitWindowColors(&dwnd);
  698.     SaveBorder(dwnd.rc);
  699.     RepaintBorder(&dwnd, NULL);
  700. }
  701. /* ---- write the dummy window border for sizing ---- */
  702. static void near sizeborder(WINDOW wnd, int rt, int bt)
  703. {
  704.     int leftmost = GetLeft(wnd)+10;
  705.     int topmost = GetTop(wnd)+3;
  706.     int bottommost = SCREENHEIGHT-1;
  707.     int rightmost  = SCREENWIDTH-1;
  708.     if (GetParent(wnd))    {
  709.         bottommost = min(bottommost,
  710.             GetClientBottom(GetParent(wnd)));
  711.         rightmost  = min(rightmost,
  712.             GetClientRight(GetParent(wnd)));
  713.     }
  714.     rt = min(rt, rightmost);
  715.     bt = min(bt, bottommost);
  716.     rt = max(rt, leftmost);
  717.     bt = max(bt, topmost);
  718.     SendMessage(NULL, MOUSE_CURSOR, rt, bt);
  719.  
  720.     if (rt != px || bt != py)
  721.         RestoreBorder(dwnd.rc);
  722.  
  723.     /* ------- change the dummy window -------- */
  724.     dwnd.ht = bt-dwnd.rc.tp+1;
  725.     dwnd.wd = rt-dwnd.rc.lf+1;
  726.     dwnd.rc.rt = rt;
  727.     dwnd.rc.bt = bt;
  728.     if (rt != px || bt != py)    {
  729.         px = rt;
  730.         py = bt;
  731.         SaveBorder(dwnd.rc);
  732.         RepaintBorder(&dwnd, NULL);
  733.     }
  734. }
  735. /* ----- adjust a rectangle to include the shadow ----- */
  736. static RECT adjShadow(WINDOW wnd)
  737. {
  738.     RECT rc;
  739.     rc = wnd->rc;
  740.     if (TestAttribute(wnd, SHADOW))    {
  741.         if (RectRight(rc) < SCREENWIDTH-1)
  742.             RectRight(rc)++;           
  743.         if (RectBottom(rc) < SCREENHEIGHT-1)
  744.             RectBottom(rc)++;
  745.     }
  746.     return rc;
  747. }
  748. /* --- repaint a rectangular subsection of a window --- */
  749. static void near PaintOverLap(WINDOW wnd, RECT rc)
  750. {
  751.     if (isVisible(wnd))    {
  752.         int isBorder, isTitle, isData;
  753.         isBorder = isTitle = FALSE;
  754.         isData = TRUE;
  755.         if (TestAttribute(wnd, HASBORDER))    {
  756.             isBorder =  RectLeft(rc) == 0 &&
  757.                         RectTop(rc) < WindowHeight(wnd);
  758.             isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  759.                         RectRight(rc) >= WindowWidth(wnd)-1 &&
  760.                         RectTop(rc) < WindowHeight(wnd);
  761.             isBorder |= RectTop(rc) == 0 &&
  762.                         RectLeft(rc) < WindowWidth(wnd);
  763.             isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  764.                         RectBottom(rc) >= WindowHeight(wnd)-1 &&
  765.                         RectLeft(rc) < WindowWidth(wnd);
  766.         }
  767.         else if (TestAttribute(wnd, HASTITLEBAR))
  768.             isTitle = RectTop(rc) == 0 &&
  769.                       RectLeft(rc) > 0 &&
  770.                       RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  771.  
  772.         if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  773.             isData = FALSE;
  774.         if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
  775.             isData = FALSE;
  776.         if (TestAttribute(wnd, HASBORDER))    {
  777.             if (RectRight(rc) == 0)
  778.                 isData = FALSE;
  779.             if (RectBottom(rc) == 0)
  780.                 isData = FALSE;
  781.         }
  782.         if (TestAttribute(wnd, SHADOW))
  783.             isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  784.                         RectBottom(rc) == WindowHeight(wnd);
  785.         if (isData)
  786.             SendMessage(wnd, PAINT, (PARAM) &rc, 0);
  787.         if (isBorder)
  788.             SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  789.         else if (isTitle)
  790.             DisplayTitle(wnd, &rc);
  791.     }
  792. }
  793. /* ------ paint the part of a window that is overlapped
  794.             by another window that is being hidden ------- */
  795. static void PaintOver(WINDOW wnd)
  796. {
  797.     RECT wrc, rc;
  798.     wrc = adjShadow(HiddenWindow);
  799.     rc = adjShadow(wnd);
  800.     rc = subRectangle(rc, wrc);
  801.     if (ValidRect(rc))
  802.         PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  803. }
  804. /* --- paint the overlapped parts of all children --- */
  805. static void PaintOverChildren(WINDOW pwnd)
  806. {
  807.     WINDOW cwnd = GetFirstFocusChild(pwnd);
  808.     while (cwnd != NULL)    {
  809.         if (cwnd != HiddenWindow)    {
  810.             PaintOver(cwnd);
  811.             PaintOverChildren(cwnd);
  812.         }
  813.         cwnd = GetNextFocusChild(pwnd, cwnd);
  814.     }
  815. }
  816. /* -- recursive overlapping paint of parents -- */
  817. static void PaintOverParents(WINDOW wnd)
  818. {
  819.     WINDOW pwnd = GetParent(wnd);
  820.     if (pwnd != NULL)    {
  821.         PaintOverParents(pwnd);
  822.         PaintOver(pwnd);
  823.         PaintOverChildren(pwnd);
  824.     }
  825. }
  826. /* - paint the parts of all windows that a window is over - */
  827. static void near PaintOverLappers(WINDOW wnd)
  828. {
  829.     HiddenWindow = wnd;
  830.     PaintOverParents(wnd);
  831. }
  832. /* --- paint those parts of a window that are overlapped --- */
  833. static void near PaintUnderLappers(WINDOW wnd)
  834. {
  835.     WINDOW hwnd = NextWindow(wnd);
  836.     while (hwnd != NULL)    {
  837.         /* ------- test only at document window level ------ */
  838.         WINDOW pwnd = GetParent(hwnd);
  839.         if (pwnd == NULL || GetClass(pwnd) == APPLICATION)    {
  840.             /* ---- don't bother testing self ----- */
  841.             if (isVisible(hwnd) && hwnd != wnd)    {
  842.                 /* --- see if other window is descendent --- */
  843.                 while (pwnd != NULL)    {
  844.                     if (pwnd == wnd)
  845.                         break;
  846.                     pwnd = GetParent(pwnd);
  847.                 }
  848.                 /* ----- don't test descendent overlaps ----- */
  849.                 if (pwnd == NULL)    {
  850.                     /* -- see if other window is ancestor --- */
  851.                     pwnd = GetParent(wnd);
  852.                     while (pwnd != NULL)    {
  853.                         if (pwnd == hwnd)
  854.                             break;
  855.                         pwnd = GetParent(pwnd);
  856.                     }
  857.                     /* --- don't test ancestor overlaps --- */
  858.                     if (pwnd == NULL)    {
  859.                         HiddenWindow = GetAncestor(hwnd);
  860.                         ClearVisible(HiddenWindow);
  861.                         PaintOver(wnd);
  862.                         SetVisible(HiddenWindow);
  863.                     }
  864.                 }
  865.             }
  866.         }
  867.         hwnd = NextWindow(hwnd);
  868.     }
  869.     /* --------- repaint all children of this window
  870.         the same way ----------- */
  871.     hwnd = Focus.FirstWindow;
  872.     while (hwnd != NULL)    {
  873.         if (GetParent(hwnd) == wnd)
  874.             PaintUnderLappers(hwnd);
  875.         hwnd = NextWindow(hwnd);
  876.     }
  877. }
  878. /* --- save video area to be used by dummy window border --- */
  879. static void SaveBorder(RECT rc)
  880. {
  881.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  882.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  883.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  884.         RECT lrc;
  885.         int i;
  886.         int *cp;
  887.  
  888.         lrc = rc;
  889.         RectBottom(lrc) = RectTop(lrc);
  890.         getvideo(lrc, Bsave);
  891.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  892.         getvideo(lrc, Bsave + Bwd);
  893.         cp = Bsave + Bwd * 2;
  894.         for (i = 1; i < Bht-1; i++)    {
  895.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  896.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  897.         }
  898.     }
  899. }
  900. /* ---- restore video area used by dummy window border ---- */
  901. static void RestoreBorder(RECT rc)
  902. {
  903.     if (Bsave != NULL)    {
  904.         RECT lrc;
  905.         int i;
  906.         int *cp;
  907.         lrc = rc;
  908.         RectBottom(lrc) = RectTop(lrc);
  909.         storevideo(lrc, Bsave);
  910.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  911.         storevideo(lrc, Bsave + Bwd);
  912.         cp = Bsave + Bwd * 2;
  913.         for (i = 1; i < Bht-1; i++)    {
  914.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  915.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  916.         }
  917.         free(Bsave);
  918.         Bsave = NULL;
  919.     }
  920. }
  921. /* ----- test if screen coordinates are in a window ---- */
  922. static int InsideWindow(WINDOW wnd, int x, int y)
  923. {
  924.     RECT rc;
  925.     rc = WindowRect(wnd);
  926.     if (!TestAttribute(wnd, NOCLIP))    {
  927.         WINDOW pwnd = GetParent(wnd);
  928.         while (pwnd != NULL)    {
  929.             rc = subRectangle(rc, ClientRect(pwnd));
  930.             pwnd = GetParent(pwnd);
  931.         }
  932.     }
  933.     return InsideRect(x, y, rc);
  934. }
  935. /* ----- find window that screen coordinates are in --- */
  936. WINDOW inWindow(int x, int y)
  937. {
  938.     WINDOW wnd = Focus.LastWindow;
  939.     while (wnd != NULL)    {
  940.         if (isVisible(wnd))    {
  941.             if (SendMessage(wnd, INSIDE_WINDOW, x, y))    {
  942.                 WINDOW wnd1 = GetLastChild(wnd);
  943.                 while (wnd1 != NULL)    {
  944.                     if (SendMessage(wnd1, INSIDE_WINDOW, x, y)) {
  945.                         if (isVisible(wnd1))  {
  946.                             wnd = wnd1;
  947.                             break;
  948.                         }
  949.                     }
  950.                     wnd1 = GetPrevChild(wnd, wnd1);
  951.                 }
  952.                 break;
  953.             }
  954.         }
  955.         wnd = PrevWindow(wnd);
  956.     }
  957.     return wnd;
  958. }
  959.  
  960. int isVisible(WINDOW wnd)
  961. {
  962.     while (wnd != NULL)    {
  963.         if (!isWndVisible(wnd))
  964.             return FALSE;
  965.         wnd = GetParent(wnd);
  966.     }
  967.     return TRUE;
  968. }
  969.  
  970. int isDerivedFrom(WINDOW wnd, CLASS class)
  971. {
  972.     CLASS tclass = GetClass(wnd);
  973.     while (tclass != -1)    {
  974.         if (tclass == class)
  975.             return TRUE;
  976.         tclass = (classdefs[tclass].base);
  977.     }
  978.     return FALSE;
  979. }
  980.  
  981. /* -- find the oldest document window ancestor of a window -- */
  982. WINDOW GetAncestor(WINDOW wnd)
  983. {
  984.     if (wnd != NULL)    {
  985.         while (GetParent(wnd) != NULL)    {
  986.             if (GetClass(GetParent(wnd)) == APPLICATION)
  987.                 break;
  988.             wnd = GetParent(wnd);
  989.         }
  990.     }
  991.     return wnd;
  992. }
  993.  
  994.